package cn.rwklyd.BookKeeping.util;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.Map;
/**
 * @author 键盘书生
 * @date 2024/10/14
 */
@Component
public class JwtUtils {

    private static String signKey = "atto";
     private static Long accessTokenExpire = 3600000L;   // 访问令牌有效期1h
     private static Long refreshTokenExpire = 604800000L;   // 刷新令牌有效期7天

    // 测试
//    private static Long accessTokenExpire = 30000L;   // 访问令牌有效期30秒
//    private static Long refreshTokenExpire = 60000L;   // 刷新令牌有效期1分钟

    /**
     * 生成访问令牌(Access Token)
     * @param claims JWT第二部分负载 payload 中存储的内容
     * @return 访问令牌
     */
    public static String generateAccessToken(Map<String, Object> claims){
        String jwt = Jwts.builder()    // 创建JwtBuilder对象
                .addClaims(claims)    // 添加JWT第二部分负载 payload 中存储的内容
                .signWith(SignatureAlgorithm.HS256, signKey)   // 设置签名算法和签名密钥
                .setExpiration(new Date(System.currentTimeMillis() + accessTokenExpire))   // 令牌过期时间戳
                .compact();    // 生成JWT令牌
        return jwt;            // 返回JWT令牌
    }
    
    /**
     * 生成刷新令牌(Refresh Token)
     * @param claims JWT第二部分负载 payload 中存储的内容
     * @return 刷新令牌
     */
    public static String generateRefreshToken(Map<String, Object> claims){
        String jwt = Jwts.builder()    // 创建JwtBuilder对象
                .addClaims(claims)    // 添加JWT第二部分负载 payload 中存储的内容
                .signWith(SignatureAlgorithm.HS256, signKey)   // 设置签名算法和签名密钥
                .setExpiration(new Date(System.currentTimeMillis() + refreshTokenExpire))   // 令牌过期时间戳
                .compact();    // 生成JWT令牌
        return jwt;            // 返回JWT令牌
    }
    
    /**
     * 生成JWT令牌（兼容旧方法）
     * @param claims JWT第二部分负载 payload 中存储的内容
     * @return
     */
    public static String generateJwt(Map<String, Object> claims){
        return generateAccessToken(claims);
    }

    /**
     * 解析JWT令牌
     * @param jwt JWT令牌
     * @return JWT第二部分负载 payload 中存储的内容
     */
    public static Claims parseJWT(String jwt){
        Claims claims = Jwts.parser()     // 创建JwtParser对象
                .setSigningKey(signKey)  // 设置签名密钥
                .parseClaimsJws(jwt)    // 解析JWT令牌
                .getBody();            // 获取负载
        return claims;                // 返回负载
    }
    
    /**
     * 获取JWT过期时间
     * @param jwt JWT令牌
     * @return 过期时间
     */
    public static Date getExpirationDate(String jwt) {
        Claims claims = parseJWT(jwt);
        return claims.getExpiration();
    }
    
    /**
     * 检查JWT是否即将过期
     * @param jwt JWT令牌
     * @param thresholdMillis 阈值（毫秒）
     * @return 是否即将过期
     */
    public static boolean isTokenAboutToExpire(String jwt, long thresholdMillis) {
        try {
            Date expiration = getExpirationDate(jwt);
            return expiration.getTime() - System.currentTimeMillis() < thresholdMillis;
        } catch (Exception e) {
            return true; // 解析失败，视为过期
        }
    }

    /**
     * 获取访问令牌过期时间（毫秒）
     * @return 过期时间（毫秒）
     */
    public static Long getAccessTokenExpireMillis() {
        return accessTokenExpire;
    }
    
    /**
     * 获取刷新令牌过期时间（毫秒）
     * @return 过期时间（毫秒）
     */
    public static Long getRefreshTokenExpireMillis() {
        return refreshTokenExpire;
    }
}

